package com.cjc.eas.ui;

import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import java.awt.Point;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;

/**
 * @param
 * @ClassName DefaultGridBagTableModel
 * @Description //TODO
 * @Date 2021/5/3116:41
 * @Author tssxs_001@163.com
 * @Version 1.0
 **/

public class DefaultGridBagTableModel implements GridBagModel, TableModelListener {
    protected AbstractTableModel model;
    protected List<List<Point>> gridInfo = null;

    DefaultGridBagTableModel(AbstractTableModel model){
        gridInfo = new Vector<List<Point>>();
        setTableModel(model);
    }

    public void setTableModel(AbstractTableModel model){
        if( model != null && model != this.model ){
            if( this.model != null )
                this.model.removeTableModelListener(this);
            //防止多次添加监听器
            model.removeTableModelListener(this);
            model.addTableModelListener(this);
            this.model = model;
            clearMergence();
        }
    }

    public void clearMergence(){
        if( gridInfo == null  )
            gridInfo = new Vector<List<Point>>();
        else
            gridInfo.clear();

        if( model == null )
            return;

        //初始化，每个格子占的格子数为(1,1);
        for(int row=model.getRowCount(); --row>=0;){
            List<Point> infos = new Vector<Point>();
            gridInfo.add(infos);
            for(int col=model.getColumnCount(); --col>=0;){
                infos.add(getDefaultPoint());
            }
        }
    }

    public Point getDefaultPoint(){
        return new Point(1,1);
    }

    @Override
    public boolean canMergeCells(int[] rows, int[] columns) {
        if( rows == null || columns == null ) return false;
        Arrays.sort(rows);
        for(int index=0; index<rows.length-1; index++){
            if( rows[index+1] - rows[index] > 1 )
                return false;
        }
        Arrays.sort(columns);
        for(int index=0; index<columns.length-1; index++){
            if( columns[index+1] - columns[index] > 1 )
                return false;
        }
        return true;
    }

    @Override
    public int getCellState(int row, int column) {
        Point grid = getGrid(row, column);
        if( grid == null ) return DEFAULT;
        if( grid.x>1 || grid.y>1 )
            return MERGE;
        if( grid.x<=0 || grid.y<=0 )
            return COVERED;
        return DEFAULT;
    }

    @Override
    public int getColumnGrid(int row, int column) {
        if( gridInfo != null && row >=0 && row < gridInfo.size() ){
            List<Point> gridRow = gridInfo.get(row);
            if( gridRow != null && column >=0 && column < gridRow.size() ){
                Point point = gridRow.get(column);
                if( point != null )
                    return point.x;
            }
        }
        return 1;
    }

    @Override
    public Point getGrid(int row, int column) {
        if( gridInfo != null && row >=0 && row < gridInfo.size() ){
            List<Point> gridRow = gridInfo.get(row);
            if( gridRow != null && column >=0 && column < gridRow.size() ){
                return gridRow.get(column);
            }
        }
        return getDefaultPoint();
    }

    @Override
    public int getRowGrid(int row, int column) {
        if( gridInfo != null && row >=0 && row < gridInfo.size() ){
            List<Point> gridRow = gridInfo.get(row);
            if( gridRow != null && column >=0 && column < gridRow.size() ){
                Point point = gridRow.get(column);
                if( point != null )
                    return point.y;
            }
        }
        return 1;
    }

    protected boolean setGrid(int row, int column, Point grid) {
        if( gridInfo != null && row >=0 && row < gridInfo.size() ){
            List<Point> gridRow = gridInfo.get(row);
            if( gridRow != null && column >=0 && column < gridRow.size() ){
                Point point = gridRow.get(column);
                if( point != null ){
                    point.setLocation(grid);
                }
                else{
                    gridRow.set(column, grid.getLocation());
                }
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean spliteCellAt(int row, int column) {
        if( gridInfo != null && row >=0 && row < gridInfo.size() ){
            List<Point> gridRow = gridInfo.get(row);
            if( gridRow != null && column >=0 && column < gridRow.size() ){
                Point point = gridRow.get(column);
                if( point != null ){
                    point = point.getLocation();
                    for(int a=0; a<point.y; a++){
                        for(int b=0; b<point.x; b++){
                            setGrid(row+a, column+b, getDefaultPoint());
                        }
                    }
                }
                else{
                    gridRow.set(column, getDefaultPoint());
                }
                return true;
            }
        }
        return false;
    }

    @Override
    /**
     * table中发生行的添加和删除的时候需要修改该模型
     */
    public void tableChanged(TableModelEvent e) {
        //TODO
    }

    @Override
    public boolean mergeCells(int[] rows, int[] columns) {
        if( !canMergeCells(rows, columns) )
            return false;
        Arrays.sort(rows);
        Arrays.sort(columns);
        return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
    }

    @Override
    public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {
        setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));
        for(int row=startRow; row<=endRow; row++){
            for(int col=startColumn; col<=endColumn; col++){
                if(row==startRow&&col==startColumn)
                    continue;
                else
                    setGrid(row, col, new Point(COVERED,COVERED));
            }
        }
        return true;
    }

    public String toString(){
        if( gridInfo == null )
            return "";
        StringBuffer sb = new StringBuffer();
        for(List<Point> rowInfo : gridInfo ){
            for(Point grid : rowInfo){
                sb.append("["+grid.x+","+grid.y+"], ");
            }
            sb.append("\n");
        }
        return sb.toString();
    }
}
